package com.haoyun.common.utils;

import com.haoyun.common.constant.CommonConstant;
import com.haoyun.common.core.BaseException;
import com.xiaoleilu.hutool.http.HttpRequest;
import com.xiaoleilu.hutool.http.HttpResponse;
import com.xiaoleilu.hutool.http.HttpUtil;
import com.xiaoleilu.hutool.json.JSONObject;
import com.xiaoleilu.hutool.json.JSONUtil;
import com.xiaoleilu.hutool.lang.Assert;
import com.xiaoleilu.hutool.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;

import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;

/**
 * @author lengleng
 * @date 2017/11/20
 * 用户相关工具类
 * @InheritableThreadLocal
 * ThreadLocal有一个问题，就是它只保证在同一个线程间共享变量，也就是说如果这个线程起了一个新线程，那么新线程是不会得到父线程的变量信息的。
 * 因此，为了保证子线程可以拥有父线程的某些变量视图，JDK提供了一个数据结构，InheritableThreadLocal。
 */
@Slf4j
public final class UserUtil {
    private static final ThreadLocal<String> THREAD_LOCAL_USER = new InheritableThreadLocal<String>();
    private static final String KEY_USER = "user";

    /**
     * 根据请求heard中的token获取用户角色
     *
     * @param httpServletRequest request
     * @return 角色名
     */
    public static Object getUser(HttpServletRequest httpServletRequest, String userInfoUri) throws BaseException {
        Assert.notBlank(userInfoUri,"不能获取安全oauth2资源用户信息URI配置信息!");
        String token = getToken(httpServletRequest);
        HttpRequest result = HttpUtil.createGet(userInfoUri);
        result.header(CommonConstant.REQ_HEADER, CommonConstant.TOKEN_SPLIT + token);
        HttpResponse response = result.execute();
        String body = response.body();
        if (StrUtil.isBlank(body)) {
            log.info("通过token：{}，获取用户信息为空！", token);
            return null;
        }
        JSONObject array = JSONUtil.parseObj(body);
        if (!"0".equals(array.get("code").toString())) {
            return null;
        }
        JSONObject data = (JSONObject) array.get("data");
        setUser((String) data.get("userName"));
        return data;
    }


    /**
     * 设置用户信息
     *
     * @param username 用户名
     */
    public static void setUser(String username) {
        THREAD_LOCAL_USER.set(username);
        MDC.put(KEY_USER, username);
    }

    /**
     * 如果没有登录，返回null
     *
     * @return 用户名
     */
    public static String getUserName() {
        return THREAD_LOCAL_USER.get();
    }

    public static void clearAllUserInfo() {
        THREAD_LOCAL_USER.remove();
        MDC.remove(KEY_USER);
    }

    /**
     * 获取请求中token
     *
     * @param request
     * @return
     */
    public static String getToken(HttpServletRequest request)throws BaseException {
        String header = request.getHeader(CommonConstant.REQ_HEADER);
        if (StrUtil.isBlank(header) || !header.startsWith(CommonConstant.TOKEN_SPLIT)) {
            throw new BaseException("请求头信息有误！");
        }
        String token = StringUtils.substringAfter(header, CommonConstant.TOKEN_SPLIT);
        if (StrUtil.isBlank(token)) {
            throw new BaseException("请求头密钥不能为空！");
        }
        return token;
    }
}
